require "wondercap/lib/utils/dependency_resolver"
require "wondercap/lib/utils/logging"

require "yaml"

define_name_filter :add_build_dependent, lambda { |names, base_conf|
  local_area = Wondercap::Deployment::Area.find_by_name("local")
  return names unless local_area && local_area.current_snapshot

  getter = lambda do |name|
    dep = local_area.current_snapshot.find_deployment_by_name(name)
    conf = base_conf.mc.find_configuration(name)
    return [] unless conf && dep

    conf = conf.clone
    conf.use(:explicit).for(:revision) { set :revision, dep.revision }
    conf.use(:stored_build_dependencies).for(:dependencies)

    conf.build_dependencies
  end

  deps_resolver = DependencyResolver.new(getter)
  deps_resolver.add_dependent(names, local_area.current_snapshot.deployments.map { |dep| dep.name })
}

define_name_filter :add_build_required, lambda { |names, base_conf|
  return names if base_conf.fetch(:remote, false)
  
  getter = lambda do |name|
    conf = base_conf.mc.find_configuration(name)
    return [] unless conf

    conf.build_dependencies
  end
  
  deps_resolver = DependencyResolver.new(getter)
  result = deps_resolver.add_required(names).to_a
  result.each do |name|
    next if names.include?(name)
    
    conf = base_conf.mc.find_configuration(name)
    next unless conf
    
    conf.use(:current_local_snapshot_with_fallback).for(:revision)
  end
}

define_name_filter :order_by_build_dependencies, lambda { |names, base_conf|
  return names if base_conf.fetch(:remote, false)

  getter = lambda do |name|
    conf = base_conf.mc.find_configuration(name)
    return [] unless conf

    #TODO: check if it works without adding conf.runtime_dependencies
    conf.build_dependencies + conf.runtime_dependencies
  end

  deps_resolver = DependencyResolver.new(getter)
  deps_resolver.order_by_dependencies(names).to_a
}

define_extension :dependencies, :build_dependencies do
  set :build_dependencies, []
  
  task :patch_dist do
    execute_previous
    
    build_deps_file = File.join(revision_build.patched_dist_path, ".build_deps")
    open(build_deps_file, "w") do |fio|
      fio.write(build_dependencies.to_yaml)
    end
  end
end

define_extension :build_dependencies, :explicit, :conf_arg => lambda { fetch(:build_dependencies, []) } do
  set(:build_dependencies) do
    conf_arg
  end
end

define_extension :dependencies, :stored_build_dependencies do
  set(:build_dependencies) do
    build_deps_file = File.join(revision_build.patched_dist_path, ".build_deps")
    if File.exists? build_deps_file
      open(build_deps_file, "r") do |fio|
        YAML::load(fio.read)
      end
    else
      []
    end
  end
end

mc.initializers << lambda { |name, conf| 
  conf.use(:build_dependencies).for(:dependencies)
}

after "wondercap:process_filters" do
  wondercap.filters << get_name_filter(:add_build_required) << get_name_filter(:order_by_build_dependencies)
end
